package com.lagou.handler;

import com.lagou.pojo.MappedStatement;
import com.lagou.mapping.SqlCommandType;
import com.lagou.session.SqlSession;

import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * Mapper代理
 * @author zhengzc
 * @version 1.0.0
 * @date 2020/2/24 22:29
 */
public class MapperProxy<T> implements InvocationHandler, Serializable {
    private final SqlSession sqlSession;

    public MapperProxy(SqlSession sqlSession) {
        this.sqlSession = sqlSession;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] param) throws Throwable {
        Object result = null;
        String methodName = method.getName();
        String className = method.getDeclaringClass().getName();

        String statementId = className+"."+methodName;
        SqlCommandType sqlCommandType = getSqlCommandType(statementId,sqlSession);
        switch(sqlCommandType) {
            case INSERT:
                result = sqlSession.insert(statementId, param);
                break;
            case UPDATE:
                result = sqlSession.update(statementId, param);
                break;
            case DELETE:
                result = sqlSession.delete(statementId, param);
                break;
            case SELECT:
                // 获取被调用方法的返回值类型
                Type genericReturnType = method.getGenericReturnType();
                // 判断是否进行了 泛型类型参数化
                if(genericReturnType instanceof ParameterizedType){
                    result = sqlSession.selectList(statementId, param);
                }else {
                    result = sqlSession.selectOne(statementId, param);
                }
                break;
            case FLUSH:
                break;
            default:
                throw new Exception("Unknown execution method for: " + statementId);
        }
        return result;
    }

    private SqlCommandType getSqlCommandType(String statementId,SqlSession sqlSession){
        MappedStatement statement = sqlSession.getConfiguration().getMappedStatementMap().get(statementId);
        if (statement != null){
            return statement.getSqlCommandType();
        }
        return null;
    }
}
